<?php
/////////////////////////////////////////////////////////////////////////////
// 
//
// workflow_system 
//
// workflow_copyright
// 
/////////////////////////////////////////////////////////////////////////////

/**
 * FILE_NAME : system_sqlback.class.php   FILE_PATH : \\classes\application\system_sqlback.class.php
 * 数据库备份操作类
 *
 * @copyright workflow_system 
 * @author 
 * @package 
 * @subpackage 
 * @version Fri Dec 07 15:37:36 CST 2007
 */

class SqlBackClass extends FrameWork {
		/**
		 * 构造函数
		 */
		function SqlBackClass(){
			$this->__construct();
		}
		function __construct(){
			//获取配置信息
			$this->_getConfiginfo();
		}
		
		/**
		 * 设置备份文件头信息
		 *
		 * @param int $remark 文件注释
		 * @return string
		 */
		function setHeader($remark=''){
			$head = "#- ShopNC SQL Dump\n".
					"#- http://www.shopnc.net\n".
					"#-\n".
					"#- HostName:".$this->_dbconfig['servername_write']."\n".
					"#- Date:".date('Y-m-d H:i:s')."\r\n".
					"#-\n".
					"#- Remark:".$remark."\n".
					"#- DataBaseName:".$this->_dbconfig['databasename_write']."\n".
					"#-\n\n".
					"#- ----------------------------------------------------------\n\n";
			return $head;
		}
		
		/**
		 * 取表名列表
		 * @author workflow Develop Team
		 * @param  
		 * @return array
		 */
		function sqlList(){
			$sql = "SHOW table status";
			$sql_list = $GLOBALS['db']->GetArray($sql);
			//对列表进行筛选，只显示商城的数据库信息
			if (is_array($sql_list)){
				$array = array();
				foreach ($sql_list as $k => $v){
					if (strstr($v['Name'],$this->_configinfo['database']['dbprefix'])){
						$array[] = $v;
					}
				}
			}
			return $array;
		}
		
		/**
		 * 优化表
		 * @author workflow Develop Team
		 * @param  数据表表名$table_name
		 * @return bool
		 */
		function optimizeTable($table_name){
			$sql = "OPTIMIZE TABLE ".$table_name;
			$query = $GLOBALS['db']->Execute($sql);
			return true;
		}
		
		/**
		 * 取表结构
		 * @author workflow Develop Team
		 * @param  
		 * @return string
		 */
		function infoTable($table_name){
			$sql = "SHOW CREATE TABLE ".$table_name;
			$array = $GLOBALS['db']->GetArray($sql);
			return $array[0]['Create Table'];
		}
		
		/**
		 * 获取一个表的结构
		 *
		 * @param string $table_name
		 * @return string
		 */
		function getTableStructSql($table_name){
			
			$sql_table = "#--\n#-- TableStruct:".$table_name."\n#--\r\n";
			
			$sql_table .= "DROP TABLE IF EXISTS $table_name;\n";
	        $Sql   = "SHOW CREATE TABLE ".$table_name;
			$query = $GLOBALS['db']->GetRow($Sql);			

		  	$sql_table .= str_replace( "`", "", $query['Create Table'].";\n" );
		  	return $tabledump.$sql_table;
		}
		/**
		 * 获取一个表的数据
		 *
		 * @param string $table_name
		 * @return string
		 */
		function getTableDataSql($table_name){
		  	/*取表中数据集*/
		  	$sql = "SELECT * FROM ".$table_name;
		  	$array = $GLOBALS['db']->GetArray($sql);
		  	$sql_rs = $GLOBALS['db']->Execute($sql);

			/*数据表字段*/
			$field_num = $GLOBALS['db']->FieldCount($sql_rs);
		  	for( $i = 0; $i < $field_num; $i++ )
			{
				/*取字段名*/
				$line = $GLOBALS['db']->FetchField($sql_rs,$i);
				$field_list .= $line . ",";
			}
		  	$field_list = preg_replace( "/,$/", "", $field_list );
		  	
			if (is_array($array) && !empty($array)){
				foreach ($array as $k => $v){
					for( $i = 0; $i < $field_num; $i++ ){
						/*取字段名*/
						$line = $GLOBALS['db']->FetchField($sql_rs,$i);
						if ( ! isset($v[$line]) ){
							$data_list .= " NULL,";
						}elseif ( $v[$line] != '' ){
							$data_list .= "'".$this->SqlAddSlashes($v[$line])."',";
						}else{
							$data_list .= "'',";
						}
					}
					$data_list = preg_replace( "/,$/","", $data_list );
					$sql_table[] ="INSERT INTO `$table_name` ($field_list) VALUES($data_list);\n";
					unset($data_list);
				}
			}
		  	return $sql_table;
		}
		/**
		 * 备份数据库
		 * 
		 * @param array $table_name_array
		 */
		function dumpSql($table_name_array,$vol_array){
			
			$vol_remark = $vol_array['vol_remark'];//文件备注
			$vol_size = $vol_array['vol_size'];//文件大小 
			$max_size = $vol_size*1024;//文件大小
			$random = mt_rand(1000,9999);
			
			$tables_count = count($table_name_array);
			$sql = "";
			/*取数据表语句*/
			for ($i=0; $i<$tables_count; $i++){
				$struct_sql[$i] = $this->getTableStructSql($table_name_array[$i]);
				$table_sql[$i] = $this->getTableDataSql($table_name_array[$i]);
			}
			$line = 1;
			/*循环表名 按照规定大小写入文件 */
			for ($i=0; $i<$tables_count; $i++){
				$sqldump = $struct_sql[$i];
				$sql .= $sqldump;
				for ($j=0;$j<count($table_sql[$i]);$j++){
					if(strlen($sql) <= $max_size){
						$sql .= $table_sql[$i][$j];
					}else {/*如果大于规定文件大小,则写入文件，清空sql*/
						/*写入文本*/
						$head = $this->setHeader($vol_remark);
						$this->putFile($head.$sql,$random,$line);
						$sql = $table_sql[$i][$j];
						$line++;
					}
				}
			}
			/*循环结束后，剩余没有写入文件的SQL*/
			if ($sql != ''){
				$head = $this->setHeader($vol_remark);
				$this->putFile($head.$sql,$random,$line);
			}

			return true;
		}
		
		/**
		 * 将sql备份到文件里
		 *
		 * @param string $random 随机数 $vol 分卷
		 * @param int $vol
		 */
		function putFile($create_sql,$random,$vol){
			/*取间隔符*/
			$intervals = $this->getIntervals();
			
			$create_file = "..".$intervals."sqlback".$intervals.$this->_dbconfig['databasename_write'].'_'.date("Ymd",time())."_".$random."_".$vol.".sql";
			if (is_file($create_file)){
				@unlink ($create_file);
			}
			if(!file_exists($create_file))		//判断是否存在文件
			{
				@chmod("..".$intervals."sqlback".$intervals,0777);	//修改文件夹属性
			}
			$fp = @fopen($create_file,"wb");
			if(!is_writeable($create_file))	//判断文件是否可写
			{
				@chmod($create_file,0777);		//修改文件属性
			}
			@fputs($fp,$create_sql);
			@fclose($fp);
		}
		
		function SqlAddSlashes($data){
			$data = str_replace('\\', '\\\\', $data);
	        $data = str_replace('\'', '\\\'', $data);
	        $data = str_replace("\r", '\r'  , $data);
	        $data = str_replace("\n", '\n'  , $data);
	        return $data;
		}
		
		
		/**
		 * 恢复数据库
		 * 
		 * @param $sql_file sql文件
		 * @return unknown
		 */
		function do_safe_restore($sql_file){
			set_time_limit(0);//设置超时时间为0，表示一直执行。当php在safe mode模式下无效，此时可能会导致导入超时，此时需要分段导入
			/*取间隔符*/
			$intervals = $this->getIntervals();
			foreach ($sql_file as $k => $v){
				$file = @fopen("..".$intervals."sqlback".$intervals.$v,'rb');
				$i=0;
				while ($line=@fgets($file)) {
					if ($line[0] != '#'){
						if (substr(trim($line),-1,1) != ';'){
							$sql .= $line;
						}else {
							$sql .= $line;
							$GLOBALS['db']->Execute($sql);
							unset($sql);
						}
						$i++;
					}
				}
				@fclose($file);
			}
			return true;			
		}

        /**
         * 取文件间隔符 win/unix
         * @author 
         * @param  
         * @return string
         */
        function getIntervals(){
        	$os=@php_uname();
			if(preg_match("|win|i",$os)){
				$b="\\";
			}else{
				$b="/";
			}
			return $b;
        }
        
        /**
         * 取文件备份
         * @author 
         * @param  
         * @return string
         */
        function getFileRemark($filename){
        	if (file_exists($filename)) {
        		$file = @fopen($filename,'rb');
				$i=0;
				while ($line=@fgets($file)) {
					if (strstr($line,'Remark:')){
						$string = explode('Remark:',$line);
						$string = $string[1];
						break;
					}
					$i++;
				}
				@fclose($file);
        	}
        	return $string;
        }
	}
?>